#ifndef _USET_TEST_H_
#define _USET_TEST_H_

#include "util.h"

U_set s1, s2, s3;

const int data1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
const int data2[5] = {1, 3, 5, 7, 9};
const int data3[5] = {2, 4, 6, 8, 10};

SETUP(uset)
{
    s1 = U_setNew();
    s2 = U_setNew();
    s3 = U_setNew();
};

DESTROY(uset)
{
    U_setDestroy(&s1);
    U_setDestroy(&s2);
    U_setDestroy(&s3);
};

TEST(uset, has)
{
    int i;
    U_setClear(s1);
    for(i = 0; i<10; i ++ )
        U_setInsert(s1, (void*)data1[i]);
    for(i = 0; i<10; i ++ )
        ctf_assert("uset should have elements inserted into it",
                   U_setHas(s1, (void*)data1[i]));
    return 0;
}

TEST(uset, add2)
{
    int i;
    U_setClear(s1);
    U_setClear(s2);
    for(i = 0; i<5; i ++ )
    {
        U_setInsert(s1, (void*)data2[i]);
        U_setInsert(s2, (void*)data2[i]);
    }
    for(i = 0; i<5; i ++ )
        U_setInsert(s3, (void*)data3[i]);
    
    U_setAdd2(s3, s1);
    ctf_assert("set's count should be accumulated after uset_add2",
                U_setGetCount(s3) == 10);
    U_setAdd2(s2, s1);
    ctf_assert("set's count should be the same after uset_add2 if sets are the same", 
               U_setGetCount(s2) == 5);
    return 0;
};

TEST(uset, remove)
{
    int i, j;

    U_setClear(s1);
    for(i = 0; i<5; i ++ )
    {
        U_setInsert(s1, (void*)data2[i]);
    }

    for(i = 0; i<5; i ++ )
    {
        U_setRemove(s1, (void*)data2[i]);
        ctf_assert("removed elements should no longer exist in set",
                   ! U_setHas(s1, (void*)data2[i]));
        ctf_assert("set's count should decrease after remove a element",
                   U_setGetCount(s1) == 4-i);
        for(j = i + 1; j<5; j ++ )
            ctf_assert_cmd("elements not removed should still in set",
                           U_setHas(s1, (void*)data2[j]),
                           printf("i=%d, j=%d, data=%d\n", i, j, data2[j]) );
    }
    return 0;
}
TEST(uset, sub2)
{
    int i;

    U_setClear(s1);
    U_setClear(s2);
    U_setClear(s3);

    for(i = 0; i<5; i ++ )
    {
        U_setInsert(s1, (void*)data2[i]);
        U_setInsert(s2, (void*)data2[i]);
    }

    for(i = 0; i<5; i ++ )
        U_setInsert(s3, (void*)data3[i]);

    U_setSub2(s1, s2);
    ctf_assert("s1 should be empty after U_setSub2(s1, s2) if s1 == s2",
               U_setGetCount(s1) == 0);
    printf("1st sub done\n");
    U_setSub2(s2, s3);
    ctf_assert("s2 should remain not modified after U_sebSub2(s2, s3) if s2 and s3 have no the same elements",
               U_setGetCount(s2) == 5);
    U_setSub2(s3, s2);
    ctf_assert("s3 should remain not modified after U_sebSub2(s2, s3) if s3 and s2 have no the same elements",
               U_setGetCount(s3) == 5);
    return 0;
};

#endif /* _USET_TEST_H_ */
